package com.test;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author Sanmier
 * @version 1.0
 * @date 2024/4/27
 */
@Slf4j
public class Parallel {

    @Test
    public void timeConsumingUtil(){
        long start = System.currentTimeMillis();
        List<Integer> list = Arrays.asList(new Integer[]{1,4,9,16});
        List<Integer> result;
        //并行
        result = simpleParallel(list);
        log.info("处理总耗时 {} , 结果：{}",(System.currentTimeMillis()-start),result);
    }


    public List<Integer> simpleParallel(List<Integer> list){
        ThreadPoolExecutor executor = new ThreadPoolExecutor(20, 20, 0L, TimeUnit.SECONDS, new SynchronousQueue<>());
        List<CompletableFuture<Integer>> futures = new ArrayList<>();
        for(Integer i:list){
            TimeConsumingUtil timeConsumingUtil = new TimeConsumingUtil(i);
            futures.add(CompletableFuture.supplyAsync(()-> timeConsumingUtil.square(),executor));
        }
        // 使用allOf方法来表示所有的并行任务
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
        // 下面的方法可以帮助我们获得所有子任务的处理结果
        CompletableFuture<List<Integer>> finalResults = allFutures.thenApply(v ->
                futures.stream().map(CompletableFuture::join).collect(Collectors.toList())
        );
        return finalResults.join();
    }

    @Slf4j
    public static class TimeConsumingUtil {

        private int num = 0;
        public TimeConsumingUtil(int num){
            this.num = num;
        }

        public int square(){
            long start = System.currentTimeMillis();
            try {
                Thread.sleep(1000);
            }catch (Exception e){
                e.printStackTrace();
            }
            log.info("线程：{} , 耗时 {} ms",Thread.currentThread().getName(),(System.currentTimeMillis()-start));
            return num*num;
        }

    }
}


